//! Level 0 descriptor (P4D)
//!

use crate::vm::addr::paddr::Paddr;

use super::prot::{PXD_TABLE_PXN, PXD_TABLE_UXN, PXD_TYPE_TABLE};

pub struct P4DTable(u64);

impl P4DTable {
    pub fn new() -> Self {
        Self(0)
    }

    #[inline]
    fn p4d_populate(&mut self, xn: u64, phys: Paddr) {
        let value = PXD_TYPE_TABLE | xn | phys.to_value() as u64;
        self.0 = value;
    }

    #[inline]
    pub fn user_table(&mut self, phys: Paddr) {
        self.p4d_populate(PXD_TABLE_PXN, phys);
    }
    #[inline]
    pub fn kernel_table(&mut self, phys: Paddr) {
        self.p4d_populate(PXD_TABLE_UXN, phys);
    }

    #[inline]
    pub fn to_value(&self) -> u64 {
        self.0
    }
}

impl Default for P4DTable {
    fn default() -> Self {
        Self::new()
    }
}
